package glasspanel.GlassDragAndDrop;

/*
 * Copyright (c) 2007, Romain Guy
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.WindowConstants;

import swinglayout.GroupLayout;
import swinglayout.LayoutStyle;

/**
 * 
 * @author Romain Guy
 */
public class ApplicationFrame extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private PictureGlassPane glassPane = new PictureGlassPane();

	public ApplicationFrame() {
		setContentPane(new JPanel(new BorderLayout()) {
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;
			private BufferedImage image = null;

			@Override
			public boolean isOpaque() {
				return imageList.getModel().getSize() > 0;
			}

			@Override
			protected void paintComponent(Graphics g) {
				Rectangle clip = g.getClipBounds();

				g.setColor(Color.WHITE);
				g.fillRect(clip.x, clip.y, clip.width, clip.height);

				if (image == null) {
					try {
						image = ImageIO.read(getClass().getResource(
								"images/drop-here.png"));
					} catch (IOException ioe) {
						ioe.printStackTrace();
					}
				}

				g.drawImage(image, (getWidth() - image.getWidth()) / 2,
						(getHeight() - image.getHeight()) / 2, null);
			}
		});

		initComponents();

		imageList.setOpaque(false);
		listScroller.setOpaque(false);
		listScroller.getViewport().setOpaque(false);

		setGlassPane(glassPane);
		imageList.setModel(new DefaultListModel());
		imageList.setTransferHandler(new FileDropHandler());
		imageList.addPropertyChangeListener("dropLocation",
				new PropertyChangeListener() {
					public void propertyChange(PropertyChangeEvent evt) {
						glassPane.moveIt(MouseInfo.getPointerInfo()
								.getLocation());
					}
				});
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed" desc=" Generated Code
	// ">//GEN-BEGIN:initComponents
	private void initComponents() {
		JLabel jLabel1;
		JLabel jLabel2;
		JLabel jLabel3;
		JPanel jPanel1;
		JSeparator jSeparator1;

		listScroller = new JScrollPane();
		imageList = new JList();
		jPanel1 = new JPanel();
		jLabel1 = new JLabel();
		jLabel2 = new JLabel();
		jLabel3 = new JLabel();
		jSeparator1 = new JSeparator();

		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setTitle("Glass Drag and Drop");
		imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		imageList.setVisibleRowCount(-1);
		listScroller.setViewportView(imageList);

		jPanel1.setBackground(new java.awt.Color(255, 255, 255));
		jLabel1.setIcon(new ImageIcon(getClass().getResource(
				"/glasspanel/GlassDragAndDrop/images/app-icon.png")));

		jLabel2.setFont(jLabel2.getFont().deriveFont(
				jLabel2.getFont().getStyle() | java.awt.Font.BOLD,
				jLabel2.getFont().getSize() + 2));
		jLabel2.setText("Glass Drag and Drop");

		jLabel3
				.setText("Drag and drop image files (PNG or JPEG) onto the application.");

		GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
		jPanel1.setLayout(jPanel1Layout);
		jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(
				GroupLayout.LEADING).add(
				jPanel1Layout.createSequentialGroup().addContainerGap().add(
						jLabel1).addPreferredGap(LayoutStyle.RELATED).add(
						jPanel1Layout.createParallelGroup(GroupLayout.LEADING)
								.add(jLabel2).add(jLabel3)).addContainerGap(
						158, Short.MAX_VALUE)));
		jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(
				GroupLayout.LEADING).add(
				jPanel1Layout.createSequentialGroup().addContainerGap().add(
						jPanel1Layout.createParallelGroup(GroupLayout.LEADING)
								.add(
										jPanel1Layout.createSequentialGroup()
												.add(jLabel2).addPreferredGap(
														LayoutStyle.RELATED)
												.add(jLabel3)).add(jLabel1))
						.addContainerGap(GroupLayout.DEFAULT_SIZE,
								Short.MAX_VALUE)));

		GroupLayout layout = new GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout.createParallelGroup(
				GroupLayout.LEADING).add(jPanel1, GroupLayout.DEFAULT_SIZE,
				GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).add(jSeparator1,
				GroupLayout.DEFAULT_SIZE, 618, Short.MAX_VALUE).add(
				layout.createSequentialGroup().addContainerGap().add(
						listScroller, GroupLayout.DEFAULT_SIZE, 578,
						Short.MAX_VALUE).addContainerGap()));
		layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.LEADING)
				.add(
						layout.createSequentialGroup().add(jPanel1,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.DEFAULT_SIZE,
								GroupLayout.PREFERRED_SIZE).add(0, 0, 0).add(
								jSeparator1, GroupLayout.PREFERRED_SIZE, 10,
								GroupLayout.PREFERRED_SIZE).addPreferredGap(
								LayoutStyle.RELATED).add(listScroller,
								GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
								.addContainerGap()));
		pack();
		java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit()
				.getScreenSize();
		java.awt.Dimension dialogSize = getSize();
		setLocation((screenSize.width - dialogSize.width) / 2,
				(screenSize.height - dialogSize.height) / 2);
	}// </editor-fold>//GEN-END:initComponents

	class FileDropHandler extends TransferHandler {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private boolean imported = false;
		private List<File> fileList;

		@SuppressWarnings("unchecked")
		public boolean canImport(TransferSupport support) {
			if (!support.isDrop()) {
				return false;
			}

			if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
				return false;
			}

			boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;

			if (copySupported) {
				support.setDropAction(COPY);

				if (!imported) {
					Transferable t = support.getTransferable();

					try {
						Object data = t
								.getTransferData(DataFlavor.javaFileListFlavor);
						this.fileList = (List<File>) data;
						BufferedImage image = createImage(fileList);

						if (image != null) {
							Point p = MouseInfo.getPointerInfo().getLocation();

							glassPane.showIt(image, p);
							imported = true;
						}
					} catch (UnsupportedFlavorException e) {
						return false;
					} catch (IOException e) {
						return false;
					}
				}

				return true;
			}

			return false;
		}

		private BufferedImage createImage(List<File> files) {
			List<File> imageFiles = new ArrayList<File>(3);
			for (File file : files) {
				if (file.getName().endsWith(".png")
						|| file.getName().endsWith(".jpg")) {
					imageFiles.add(file);
					if (imageFiles.size() == 3) {
						break;
					}
				}
			}

			if (imageFiles.size() == 0) {
				return null;
			}

			int width = 60 + (imageFiles.size() - 1) * 10;
			int height = 45 + (imageFiles.size() - 1) * 10;

			BufferedImage image = GraphicsUtilities
					.createCompatibleTranslucentImage(width, height);
			Graphics2D g2 = image.createGraphics();

			for (int i = 0; i < imageFiles.size(); i++) {
				File imageFile = imageFiles.get(i);
				BufferedImage externalImage = null;
				try {
					externalImage = GraphicsUtilities
							.loadCompatibleImage(imageFile.toURI().toURL());
				} catch (MalformedURLException ex) {
					ex.printStackTrace();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
				externalImage = GraphicsUtilities.createThumbnail(
						externalImage, 60, 45);
				g2.drawImage(externalImage, i * 10, i * 10, null);
			}

			g2.dispose();
			return image;
		}

		public boolean importData(TransferSupport support) {
			if (!canImport(support)) {
				return false;
			}

			if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
				return false;
			}

			for (int i = 0; i < fileList.size(); i++) {
				File imageFile = fileList.get(i);
				BufferedImage externalImage = null;
				try {
					externalImage = GraphicsUtilities
							.loadCompatibleImage(imageFile.toURI().toURL());
					externalImage = GraphicsUtilities.createThumbnail(
							externalImage, 120);
				} catch (MalformedURLException ex) {
					ex.printStackTrace();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
				((DefaultListModel) imageList.getModel()).add(0, new ImageIcon(
						externalImage));
			}

			glassPane.hideIt();
			imported = false;

			return true;
		}
	}

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				new ApplicationFrame().setVisible(true);
			}
		});
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private JList imageList;
	private JScrollPane listScroller;
	// End of variables declaration//GEN-END:variables

}
